#!/usr/bin/env bash
usage() {
  cat <<EOF
  Usage: bash ospd_util.sh [-h|--help] [--exec-path=<exec_path>] [--unix-sock=<sock_path>]
    [--pid-file=<pid_file>] [--log-file=<log_file>] [--log-level=<log_level>]
    [--python-path=<python_path>] [--setup-file=<setup_file>]
    [--scanner-name=<scanner_name>] [--pip-path=<pip_path>]
    <start|stop|status|install|uninstall|register>
  Options:
    -h: Get help message

    Used to install:
    --python-path:  sepecify the path of python interpreter.
    --setup-file:   sepecify the setup file for this OSPD scanner.

    Used to uninstall:
    --scanner-name: sepecify the scanner name.
    --pip-path:     sepecify the pip path used to uninstall this scanner.

    Used to start/stop/status:
    --exec-path:    specify the exec path used to launch an OSPD scanner.
    --unix-sock:    specify the unix socket file path used to bind an unix socket.
    --pid-file:     specify the pid file path.
    --log-file:     specify the log file path, all info will print into that file.
    --log-level:    specify the log level, e.g. DEBUG, INFO, WARN, ERROR.

    Used to register the scanner to gvm:
    TODO

  Actions:
    start:      start the OSPD scanner.
      Attention: ensure the options exec_path, unix_sock and pid_file are valid.
    stop:       stop the OSPD scanner.
      Attention: ensure the options unix_sock and pid_file are valid.
    status:     see the status of the OSPD scanner.
      Attention: ensure the options pid_file are valid.
    install:    install the OSPD scanner.
      Attention: ensure the option python_path and setup_file are valid.
    uninstall:  uninstall the OSPD scanner.
      Attention: ensure the option scanner_name and pip_path are valid.
EOF
}

# the settings below are default, you can modify in manual according to your demands.
scanner_name=ospd-nmap
exec_path=$scanner_name
unix_sock=/var/run/ospd/ospd-nmap.sock
pid_file=/var/run/ospd/ospd-nmap.pid
log_file=/tmp/ospd/$scanner_name.log
log_level=DEBUG

python_path=python3
setup_file=setup.py

pip_path=pip3

print_conf_err() {
  opt_name="$1"
  opt_val="$2"
  echo "ERROR: there are some errors in option name: $opt_name, and option val: $opt_val" >&2
  return 1
}

print_existed_err() {
  opt_name="$1"
  opt_val="$2"
  need_existed="$3"
  if [[ $need_existed == true ]]; then
    echo "ERROR: the file $opt_val existed." >&2
  else
    echo "ERROR: the file $opt_val not existed." >&2
  fi
  return 1
}

check_start() {
  # shellcheck disable=SC2230
  which $exec_path >/dev/null
  status=$?
  [[ -x "$exec_path" || $status ]] || print_conf_err 'exec_path' "$exec_path" || exit 1
  [[ ! -e "$unix_sock" ]] || print_existed_err 'unix_sock' "$unix_sock" true || exit 1
  [[ ! -e "$pid_file" ]] || print_existed_err 'pid_file' "$pid_file" true || exit 1

  unix_sock_dir=${unix_sock%/*}
  [[ -e unix_sock_dir ]] || mkdir -p $unix_sock_dir

  pid_file_dir=${pid_file%/*}
  [[ -e pid_file_dir ]] || mkdir -p $pid_file_dir

  log_file_dir=${log_file%/*}
  [[ -e $log_file_dir ]] || mkdir -p $log_file_dir

  return 0
}

check_stop() {
  [[ -e "$pid_file" ]] || print_existed_err 'pid_file' "$pid_file" false || exit 1
  [[ -e "$unix_sock" ]] || print_existed_err 'unix_sock' "$unix_sock" false || exit 1
  return 0
}

check_install() {
    # shellcheck disable=SC2230
  which $python_path >/dev/null
  status=$?
  [[ -x "$python_path" || $status ]] || print_conf_err 'python_path' "$python_path" || exit 1
  [[ -f $setup_file ]] || print_existed_err 'setup_file' "$setup_file" true || exit 1
  return 0
}

check_uninstall() {
    # shellcheck disable=SC2230
  which $pip_path >/dev/null
  status=$?
  [[ -x "$pip_path" || $status ]] || print_conf_err 'pip_path' "$pip_path" || exit 1
  return 0
}

check_register() {
  # TODO
  return 0
}

install() {
  $python_path $setup_file install
  return $?
}

uninstall() {
  $pip_path uninstall -y $scanner_name
  return $?
}

register() {
  # TODO
  return 0
}

start() {
  echo 'INFO: starting the OSPD scanner...'
  echo "INFO: create the unix socket file in $unix_sock"
  echo "INFO: create the pid file in $pid_file"
  echo "INFO: create the log file in $log_file"
  echo "INFO: the logging level is $log_level"
  $exec_path -b 127.0.0.1 -u $unix_sock --pid-file=$pid_file -l $log_file -L $log_level
  status=$?
  [[ ! -f $pid_file ]] && echo "ERROR: start the OSPD scanner failed, to get more details, plz see the log file in $log_file" >&2
  return $status
}

stop() {
  echo 'INFO: stoping the OSPD scanner...'
  pid=$(cat <$pid_file | xargs echo -n)
  echo "INFO: killing the OSPD scanner process[pid=$pid]..."
  echo "INFO: removing the sock file in $unix_sock and the pid file in $pid_file..."
  kill -9 "$pid" && rm -rf $unix_sock $pid_file
  status=$?
  [[ $status != 0 ]] && echo "ERROR: stop the OSPD scanner failed, to get more details, plz see the log file in $log_file" >&2
  return $status
}

status() {
  flag=1
  if [[ -e $pid_file ]]; then
    pid=$(cat <$pid_file | xargs echo -n)
    ps -p "$pid" >/dev/null
    flag=$?
  fi
  if [[ $flag == 0 ]]; then
    echo 'INFO: status-running'
  else
    echo 'INFO: status-stopped'
  fi
  return 0
}

RETVAL=0

while (($# > 0)); do
  case "$1" in
  --exec-path=?*)
    exec_path=$(echo "$1" | sed 's/--exec-path=//' | sed "s/['\"]//g")
    shift
    ;;
  --unix-sock=?*)
    unix_sock=$(echo "$1" | sed 's/--unix-sock=//' | sed "s/['\"]//g")
    shift
    ;;
  --pid-file=?*)
    pid_file=$(echo "$1" | sed 's/--pid-file=//' | sed "s/['\"]//g")
    shift
    ;;
  --log-file=?*)
    log_file=$(echo "$1" | sed 's/--log-file=//' | sed "s/['\"]//g")
    shift
    ;;
  --log-level=?*)
    log_level=$(echo "$1" | sed 's/--log-level=//' | sed "s/['\"]//g")
    shift
    ;;
  --python-path=?*)
    python_path=$(echo "$1" | sed 's/--python-path=//' | sed "s/['\"]//g")
    shift
    ;;
  --setup-file=?*)
    setup_file=$(echo "$1" | sed 's/--setup-file=//' | sed "s/['\"]//g")
    shift
    ;;
  --scanner-name=?*)
    scanner_name=$(echo "$1" | sed 's/--scanner-name=//' | sed "s/['\"]//g")
    shift
    ;;
  --pip-path=?*)
    pip_path=$(echo "$1" | sed 's/--pip-path=//' | sed "s/['\"]//g")
    shift
    ;;
  -h | --help)
    usage
    exit 0
    ;;
  start)
    check_start
    start
    RETVAL=$?
    break 2
    ;;
  stop)
    check_stop
    stop
    RETVAL=$?
    break 2
    ;;
  status)
    status
    exit 0
    ;;
  install)
    check_install
    install
    RETVAL=$?
    break 2
    ;;
  uninstall)
    check_uninstall
    uninstall
    RETVAL=$?
    break 2
    ;;
  register)
    check_register
    register
    RETVAL=$?
    break 2
    ;;
  *)
    echo 'Error: options you input are illeagal, more details, see -h' >&2
    exit 1
    ;;
  esac
done

[[ $RETVAL == 0 ]] && echo 'INFO: done.'

exit $RETVAL
